/*
 * ValueObj.h
 *
 *  Created on: 03/01/2011
 *      Author: wlad
 */

#ifndef VALUEOBJ_H_
#define VALUEOBJ_H_

#include <iostream>
#include "excecoes.h"

using namespace std;

#define VALUE_OBJ_EXPAND_ARRAY_STEP 10.f

/**
 * Foward definition....
 */
class ValueObj;

/**
 * Ponteiro par ValueObj
 */

typedef ValueObj* pValueObj;

typedef struct VALUE_ARRAY {
	int length;
	int size;
	pValueObj* itens;
} ValueArray, *pValueArray;

typedef union VALUE_DATA {
	long inteiro;
	float decimal;
	string* caracter;
	ValueArray array;

} ValueData, *pValueData;

typedef enum VALUE_TYPE {
	nulo, inteiro, decimal, caracter, array
} ValueType;

/**
 * Manipula valores genericos
 */
class ValueObj {
protected:

	/** Nome interno da variavel*/
	string m_nome;

	/** dados da variavel */
	ValueData m_data;

	/** tipo */
	ValueType m_tipo;

	/** array esta ordenado */
	bool m_sorted;
public:
	/**
	 * Construtor padrao
	 */
	ValueObj();

	/**
	 * Destrct
	 */
	virtual ~ValueObj();

	/**
	 * Cpy Constructor
	 * @param obj Other value
	 * @param nome nome interno da variavel
	 */
	ValueObj(ValueObj& obj, const char* nome = NULL);

	/**
	 * Int Construcor
	 * @param i valor
	 * @param nome nome da variavel
	 */
	ValueObj(int i, const char* nome = NULL);

	/**
	 * float Construcor
	 * @param d valor
	 * @param nome nome da variavel
	 */
	ValueObj(float d, const char* nome = NULL);

	/**
	 * string Construcor
	 * @param s valor
	 * @param nome nome da variavel
	 */

	ValueObj(const char* s, const char* nome = NULL);

	/**
	 * Adiciona um novo valor ao array, caso a variável não seja do tipo array então converte
	 * @param obj valor
	 */
	ValueObj& add(ValueObj* obj);

	/**
	 * Mostra em cout os dados da variavel
	 */
	void dump();

	/** @result tamanho do array
	 */
	int getLength();

	/** @result tipo de dado armazenado */
	int getTipo();

	/** @result nome interno da variavel */
	string getNome();

	/** limpa espaço alocado desnecessariamente */
	void compact();

	/*operator =int*/
	int operator=(int v);

	/*operator =float=*/
	float operator=(float v);

	/* operator= string */
	string operator=(const char* v);

	/*operator (int)*/
	operator int() const;

	/*operator (float)*/
	operator float() const;

	/*operator (string)*/
	operator string() const;

	/*operator [int] */
	ValueObj& operator [](int index);

	/*operator [nome] */
	ValueObj& operator [](const char* nome);



private:
	/*
	 * Inicializa o objeto, seta o nome e limpa os dados
	 */
	void init(const char* nome);


	/**
	 * Expande o array
	 * @param  new_length posicao no array
	 */
	void expandTo( int new_length);

	/**
	 * Libera os dados da variavel
	 *
	 */
	void freeData();

	/**
	 * procura pelo nome uma var. no array
	 * @param nome nome
	 */
	ValueObj* find(const char* nome);

	/**
	 * @return true se o array esta ordenado
	 */
	bool isSorted() {
		return m_sorted;
	}

	void limpaArray(int inicio, int fim);
};

#endif /* VALUEOBJ_H_ */
